<template>
  <div class="main">
    <div class="filter">
      <img :src="icons.recordIcon" class="record-icon">
      <div class="record-title">{{ layerName }}热力播放器</div>
      <img :src="icons.lineIcon" class="line-icon">
      <div
        class="attribute"
        :style="textColor"
        @mouseover="textColor = 'color:#ffffff'"
        @mouseleave="textColor = 'color:#6A7485'"
      >
        Y Axis
      </div>
      <div class="time-value" v-text="timeInternal" />
      <img :src="icons.closeIcon" class="fold-icon" @click="close" title="隐藏时间轴">
    </div>
    <div class="data">
      <div class="chart" id="chart" />
      <div class="setting">
        <el-tooltip
          class="box-item"
          :content="isPlay ? '暂停' : '播放'"
          effect="dark"
          placement="top"
          :show-after="500"
        >
          <img
            :src="isPlay ? icons.playIcon : icons.pauseIcon"
            class="play-icon common-icon"
            v-if="isExpand"
            @click="startPlay"
          >
        </el-tooltip>

        <el-tooltip
          class="box-item"
          :content="`${playInternal}X`"
          effect="dark"
          placement="top"
          :show-after="500"
        >
          <div class="speed-container">
            <el-popover
              placement="top"
              :width="100"
              trigger="click"
              popper-class="speed-pop"
            >
              <div class="speed-main">
                <el-slider
                  v-model="playInternal"
                  :min="0"
                  :max="10"
                  :step="0.1"
                  :show-tooltip="false"
                />
                <div class="speed-text" v-text="playInternal" />
              </div>
              <template #reference>
                <img :src="icons.speedIcon" class="speed_icon" v-if="isExpand">
              </template>
            </el-popover>
          </div>
        </el-tooltip>

        <el-tooltip
          class="box-item"
          content="重置"
          effect="dark"
          placement="top"
          :show-after="500"
        >
          <img :src="icons.resetIcon" class="play-icon common-icon" v-if="isExpand" @click="reset">
        </el-tooltip>

        <el-tooltip
          class="box-item"
          content="展开/收起"
          effect="dark"
          placement="top"
          :show-after="500"
        >
          <img :src="icons.expandIcon" class="play-icon expand-icon" @click="isExpand = !isExpand">
        </el-tooltip>

      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { computed, onMounted, reactive, ref } from 'vue'
import recordIcon from '../../assets/dialog/time_record.png'
import lineIcon from '../../assets/dialog/time_line.png'
import closeIcon from '../../assets/dialog/search_close.png'
import pauseIcon from '../../assets/dialog/time_pause.png'
import playIcon from '../../assets/dialog/time_play.png'
import speedIcon from '../../assets/dialog/time_speed.png'
import resetIcon from '../../assets/dialog/time_reset.png'
import expandIcon from '../../assets/dialog/time_expand.png'
import '@/styles/element/popover.scss'
import * as d3 from 'd3'
import { dateFormat } from '@/utils/utils'
import { ElTooltip, ElPopover, ElSlider } from 'element-plus'
const props = defineProps({
  heatData: {
    type: Array,
    default: () => []
  },
  heatKey: {
    type: String,
    default: () => ''
  },
  layerName: {
    type: String,
    default: () => ''
  }
})
const emit = defineEmits(['close', 'timeInterval'])
const icons = reactive({
  recordIcon: recordIcon,
  lineIcon: lineIcon,
  closeIcon: closeIcon,
  pauseIcon: pauseIcon,
  playIcon: playIcon,
  speedIcon: speedIcon,
  resetIcon: resetIcon,
  expandIcon: expandIcon
})

const timeInternal = ref('')
// 选中文字颜色
const textColor = ref('color:#6A7485')

// d3顶级容器
let svg: any = null
// 刷子选中区域
let brush: any = null
// 记录刷子选中区域 以用于设置选中柱子的颜色
let group: any
// 统计数据
const statisticYData = ref([] as Array<Number>)
// 设置柱子和柱子间距宽度
const rectStep = 10
// 柱子宽度
const rectWidth = 5
// 刷子能够选中的区域大小 其中最大宽度由下发数据控制
const minWidth = 0
const minHeight = 0
let maxWidth = 0
const maxHeight = 99
// 刷子开始的坐标
let startX = 0
// 刷子初始选中的x区域间隔
let brushInternal = 30
// 设置icon展开状态
const isExpand = ref(true)
// 是否在播放中
const isPlay = ref(false)
// 计时器用于播放刷子
let timer: any = {}
// 播放加速
const playInternal = ref(1.0)
const heatData:any = computed(() => props.heatData)
const heatKey:any = computed(() => props.heatKey)
let startDate = '' as any
let endDate = '' as any

onMounted(() => {
  const dataY:any = []
  const temp = {}
  if (heatData.value[0][heatKey.value]) {
    let startDateTemp = heatData.value[0][heatKey.value].split('T')
    let endDateTemp = heatData.value[0][heatKey.value].split('T')
    heatData.value.forEach((item:any) => {
      const date = item[heatKey.value].split('T')[0]
      if (date) {
        if (temp[date]) {
          temp[date] = Number(temp[date]) + 1
        } else {
          temp[date] = [1]
        }
      }
    })
    Object.keys(temp).forEach(function (key) {
      if (Date.parse(startDateTemp) < Date.parse(key)) {
        endDateTemp = key
      }
      if (Date.parse(endDateTemp) > Date.parse(key)) {
        startDateTemp = key
      }
      dataY.push(temp[key])
    })
    startDate = new Date(startDateTemp.split('-')[0], startDateTemp.split('-')[1] - 1, startDateTemp.split('-')[2])
    endDate = new Date(new Date(endDateTemp.split('-')[0], endDateTemp.split('-')[1] - 1, endDateTemp.split('-')[2]).getTime() + 24 * 60 * 60 * 1000)
    dateArray = d3.timeDays(startDate, endDate)
    statisticYData.value = dataY
    maxWidth = statisticYData.value.length * rectStep
    initChart()
  }
})

// watch(() => heatData.value, () => {
//   console.log('热力数据' + JSON.stringify(heatData.value))
//   const dataY:any = []
//   const temp = {}
//   let startDateTemp = heatData.value[0][heatKey.value].split('T')
//   let endDateTemp = heatData.value[0][heatKey.value].split('T')
//   heatData.value.forEach((item:any) => {
//     const date = item[heatKey.value].split('T')[0]
//     if (date) {
//       if (temp[date]) {
//         temp[date] = Number(temp[date]) + 1
//       } else {
//         temp[date] = [1]
//       }
//     }
//   })
//   Object.keys(temp).forEach(function (key) {
//     if (Date.parse(startDateTemp) < Date.parse(key)) {
//       endDateTemp = key
//     }
//     if (Date.parse(endDateTemp) > Date.parse(key)) {
//       startDateTemp = key
//     }
//     dataY.push(temp[key])
//   })
//   startDate = new Date(startDateTemp.split('-')[0], startDateTemp.split('-')[1] - 1, startDateTemp.split('-')[2])
//   endDate = new Date(new Date(endDateTemp.split('-')[0], endDateTemp.split('-')[1] - 1, endDateTemp.split('-')[2]).getTime() + 24 * 60 * 60 * 1000)
//   dateArray = d3.timeDays(startDate, endDate)
//   statisticYData.value = dataY
//   maxWidth = statisticYData.value.length * rectStep
//   initChart()
// }, {
//   deep: true
// })

let dateArray = d3.timeDays(startDate, endDate)
const arrayIndex = ref([])

const initChart = () => {
  const width = statisticYData.value.length * rectStep
  const height = 100
  // 将固定高度分割
  const internal = height / Math.max.apply(null, statisticYData.value as any[])

  svg = d3.select('#chart')
    .append('svg')
    .attr('width', width + 20)
    .attr('height', height + 30)

  const local = d3.timeFormatLocale({
    dateTime: '%a %b %e %X %Y',
    date: '%Y/%-m/%-d',
    time: '%H:%M:%S',
    periods: ['上午', '下午'],
    days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    shortDays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    shortMonths: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
  })
  const xScale = d3.scaleTime()
    .domain([startDate, endDate])
    .range([0, width])
  const xAxis = d3
    .axisBottom<Date>(xScale)
    .ticks(6)
    .tickFormat(local.format('%b/%e'))
    .tickPadding(20)
    .tickSize(0)

  svg.selectAll('rect') // 选择svg内所有的矩形
    .data(statisticYData.value) // 绑定数组
    .enter() // 指定选择集的enter部分
    .append('rect') // 添加足够数量的矩形元素
    .attr('y', function (d: any) {
      return height - Number(d) * internal
    })
    .attr('x', function (d: any, i: number) { // 设置X坐标
      return i * rectStep
    })
    .attr('height', function (d: any) {
      return internal * Number(d)
    })
    .attr('width', rectWidth)
    .attr('fill', '#6A7485') // 给矩形元素设置颜色
  initBrush()
  group = svg.append('g')
    .attr('class', 'brush')
    .call(brush)
  group.call(brush.move, [startX, startX + brushInternal])
  svg.append('g')
    .call(xAxis)
    .attr('transform', `translate(0, ${height})`)
    .attr('font-size', '10')
    .attr('color', '#757c88')
    .select('.domain').remove()
}

const initBrush = () => {
  const brushended = () => {
    const xGroup = d3.brushSelection(group.node())
    startX = xGroup?.[0] as number
    const endX = xGroup?.[1] as number
    brushInternal = endX - startX
    arrayIndex.value = [] as any
    d3.selectAll('rect')
      .each(function (d, i) {
        // console.log('选中' + i)
        if (i < statisticYData.value.length) {
          if ((this as Element).getAttribute('x') != null) {
            const currentX = Number((this as Element).getAttribute('x'))
            // 如果柱子在刷子范围内 则把柱体颜色设置为亮色
            if (currentX >= startX && (currentX + rectWidth / 2) < endX) {
              (this as Element).setAttribute('fill', '#2896AC')
              if (i < dateArray.length) {
                arrayIndex.value.push(i as never)
              }
            } else {
              (this as Element).setAttribute('fill', '#6A7485')
            }
          }
        }
      })
    if (arrayIndex.value.length > 0) {
      const startTime = dateFormat(dateArray[arrayIndex.value[0]], 'yyyy/MM/dd')
      const endTime = dateFormat(dateArray[arrayIndex.value[arrayIndex.value.length - 1]], 'yyyy/MM/dd')
      timeInternal.value = `${startTime} - ${endTime}`
      emit('timeInterval', timeInternal.value)
    }
  }
  // 实例化刷子
  brush = d3
    .brushX()
    .extent([[minWidth, minHeight], [maxWidth, maxHeight]])
    .on('brush', brushended)
}

const startPlay = () => {
  isPlay.value = !isPlay.value
  if (isPlay.value) {
    timer = setInterval(() => {
      if (startX + brushInternal < maxWidth) {
        startX = startX + playInternal.value
      } else {
        startX = 0
      }
      group.call(brush.move, [startX, startX + brushInternal])
    }, 20)
  } else {
    clearInterval(timer)
  }
}
// 重置
const reset = () => {
  startX = 0
  brushInternal = 30
  group.call(brush.move, [startX, startX + brushInternal])
}
// 关闭弹窗
const close = () => {
  if (timer) {
    clearInterval(timer)
  }
  emit('close')
}

</script>
<style lang="scss" scoped>
.main {
  background: #283442;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  padding: 10px 24px;

  .filter {
    display: flex;

    .record-icon {
      width: 15px;
      height: 15px;
    }

    .record-title {
      font-size: 11px;
      color: rgb(160, 167, 180);
      font-weight: 500;
      margin-left: 12px;
    }

    .line-icon {
      width: 15px;
      height: 15px;
      margin-left: 30px;
    }

    .attribute {
      font-size: 11px;
      font-weight: 500;
      margin-left: 12px;
    }

    .time-value {
      color: rgb(255, 255, 255);
      font-size: 14px;
      font-weight: 500;
      margin-left: 16px;
    }

    .fold-icon {
      width: 15px;
      height: 15px;
      margin-left: auto;
      margin-right: 0;
      cursor: pointer;
    }
  }

  .data {
    display: flex;

    .chart {
      margin-top: 10px;
    }

    .setting {
      width: 152px;
      display: flex;
      img{
        cursor: pointer;
      }

      .common-icon {
        padding: 8px;
      }

      .speed-container {
        margin-left: 7px;
        margin-top: auto;

        .speed_icon {
          width: 32px;
          height: 32px;
          padding: 6px 4px;
          background: #6A7485;
          display: flex;
          align-items: center;
          border-radius: 4px;
          justify-content: center;
          box-sizing: border-box;
        }
      }

      .play-icon {
        width: 32px;
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
        box-sizing: border-box;
        background: #6A7485;
        border-radius: 4px;
        margin-left: 7px;
        margin-top: auto;
      }

      .expand-icon {
        padding: 10px 4px;
      }
    }

  }
}
</style>
